#include "cConfig.h"

#include <Poco/Util/IniFileConfiguration.h>
#include <Poco/AutoPtr.h>
#include <Poco/Exception.h>
#include <fstream>
#include "misc/Debug.h"

Poco::Mutex* cConfig::mutex = new( Poco::Mutex );
/*********************************************************/
cConfig& cConfig::Instance()
{
	mutex->lock();
	static cConfig pInstance;
	mutex->unlock();
	return( pInstance );
}
/*********************************************************/
cConfig::cConfig()
{
	Debug::Instance() << "Config :: Parsing Configuration file: client.ini" << std::endl;
	reparse();
}
/*********************************************************/
void cConfig::reparse()
{
	Debug& DEBUG = Debug::Instance();

	// Check if nameserver.ini exists
	std::ifstream	ifile("client.ini");
	if ( ifile.is_open() ) {
		ifile.close();
	} else {
		writeDefaultConfig();
	}

	if ( !parse() ) {
		writeDefaultConfig();
		if ( !parse() ) {
			DEBUG << "Config :: Unable to parse configuration, default values corrupted or couldn't write default client.ini file to disk!" << std::endl;
			throw(std::logic_error("Unable to parse configuration, default values corrupted or couldn't write default client.ini file to disk!"));
		}
	}
}
/*********************************************************/
bool cConfig::parse()
{
	Debug& DEBUG = Debug::Instance();
	mutex->lock();
	Poco::AutoPtr<Poco::Util::IniFileConfiguration> pConf;
	try {
		// Parse the configuration file
		pConf = new Poco::Util::IniFileConfiguration("client.ini");

		// Get all required values
		pNetworkInterface = pConf->getString("Client.NetworkInterface");
		pMulticastGroup = Poco::Net::SocketAddress(pConf->getString("Client.NetworkMulticastGroup"));
		pNameServerDelay = pConf->getInt("Client.NameServerDelay");
		pMaxPacketSize = pConf->getInt("Client.MaximumPacketSize");

		mutex->unlock();
		return( true );
	} catch(Poco::NotFoundException& e ) {
		DEBUG << "Config :: Missing some Configuration parameters in client.ini!" << std::endl;
		mutex->unlock();
		return( false );
	}
}
/*********************************************************/
void cConfig::writeDefaultConfig()
{
	mutex->lock();
	std::ofstream file;
	file.open("nameserver.ini");
	file << "; Nameserver configuration parameters" << std::endl << std::endl;
	file << "[Client]" << std::endl;
	file << "NetworkInterface = "<< DEFAULT_NET_INTERFACE << std::endl;
	file << "NetworkMulticastGroup = " << DEFAULT_MULTICAST_GROUP << std::endl;
	file << "NameServerDelay = " << DEFAULT_NAMESERVER_DELAY << std::endl;
	file << "MaximumPacketSize = " << DEFAULT_MAXPACKET_SIZE << std::endl;
	file.close();
	mutex->unlock();
}
/*********************************************************/
void cConfig::setMaxPacketSize(const unsigned long& size)
{
	mutex->lock();
	pMaxPacketSize = size;
	mutex->unlock();
}
/*********************************************************/
unsigned long cConfig::getMaxPacketSize() const
{
	mutex->lock();
	unsigned long size = pMaxPacketSize;
	mutex->unlock();
	return size;
}
/*********************************************************/
std::string cConfig::getRingName() const
{
	mutex->lock();
	std::string name = pRingName;
	mutex->unlock();
	return name;
}
/*********************************************************/
void cConfig::setRingName(const std::string& rName)
{
	mutex->lock();
	pRingName = rName;
	mutex->unlock();
}
/*********************************************************/
unsigned int cConfig::getNameServerDelay() const
{
	mutex->lock();
	unsigned int nsDelay = pNameServerDelay;
	mutex->unlock();
	return nsDelay;
}
/*********************************************************/
void cConfig::setNameServerDelay(const unsigned int& nsDelay)
{
	mutex->lock();
	pNameServerDelay = nsDelay;
	mutex->unlock();
}
/*********************************************************/
std::string cConfig::getNetworkInterface() const
{
	mutex->lock();
	std::string intf = pNetworkInterface;
	mutex->unlock();
	return intf;
}
/*********************************************************/
Poco::Net::SocketAddress cConfig::getMulticastGroup() const
{
	mutex->lock();
	Poco::Net::SocketAddress addr = pMulticastGroup;
	mutex->unlock();
	return addr;
}
/*********************************************************/
void cConfig::setNetworkInterface( const std::string& intf )
{
	mutex->lock();
	pNetworkInterface = intf;
	mutex->unlock();
}
/*********************************************************/
void cConfig::setMulticastGroup( const Poco::Net::SocketAddress& mGroup ) 
{
	mutex->lock();
	pMulticastGroup = mGroup;
	mutex->unlock();
}
/*********************************************************/
cConfig::~cConfig()
{
	delete( mutex );
}
/*********************************************************/
